package io.github.qifan777.server.task.controller;

import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import com.github.binarywang.wxpay.bean.notify.SignatureHeader;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import io.github.qifan777.server.infrastructure.aop.NotRepeat;
import io.github.qifan777.server.infrastructure.model.QueryRequest;
import io.github.qifan777.server.role.repository.RoleRepository;
import io.github.qifan777.server.task.entity.TaskOrder;
import io.github.qifan777.server.task.entity.dto.TaskOrderInput;
import io.github.qifan777.server.task.entity.dto.TaskOrderSpec;
import io.github.qifan777.server.task.repository.TaskOrderRepository;
import io.github.qifan777.server.task.service.TaskOrderService;
import io.github.qifan777.server.user.root.repository.UserRepository;
import io.github.qifan777.server.user.root.repository.UserRoleRelRepository;
import io.qifan.infrastructure.common.exception.BusinessException;
import lombok.AllArgsConstructor;
import org.babyfish.jimmer.client.ApiIgnore;
import org.babyfish.jimmer.client.FetchBy;
import org.babyfish.jimmer.client.meta.DefaultFetcherOwner;
import org.springframework.data.domain.Page;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("front/task-order")
@AllArgsConstructor
@DefaultFetcherOwner(TaskOrderRepository.class)
@Transactional
public class TaskOrderForFrontController {
    private final TaskOrderRepository taskOrderRepository;
    private final TaskOrderService taskOrderService;
    private final UserRepository userRepository;
    private final RoleRepository roleRepository;
    private final UserRoleRelRepository userRoleRelRepository;

    @GetMapping("{id}")
    public @FetchBy(value = "COMPLEX_FETCHER_FOR_FRONT") TaskOrder findById(@PathVariable String id) {
        return taskOrderRepository.findById(id, TaskOrderRepository.COMPLEX_FETCHER_FOR_FRONT).orElseThrow(() -> new BusinessException("数据不存在"));
    }

    @PostMapping("query")
    public Page<@FetchBy(value = "COMPLEX_FETCHER_FOR_FRONT") TaskOrder> query(@RequestBody QueryRequest<TaskOrderSpec> queryRequest) {
        queryRequest.getQuery().setCreatorId(StpUtil.getLoginIdAsString());
        return taskOrderRepository.findPage(queryRequest, TaskOrderRepository.COMPLEX_FETCHER_FOR_FRONT);
    }

    @SaCheckRole("接单者")
    @PostMapping("query/deliver")
    public Page<@FetchBy(value = "COMPLEX_FETCHER_FOR_FRONT") TaskOrder> queryForDeliver(
            @RequestBody QueryRequest<TaskOrderSpec> queryRequest) {
        return taskOrderRepository.findPage(queryRequest, TaskOrderRepository.COMPLEX_FETCHER_FOR_FRONT);
    }

    @SaCheckRole("接单者")
    @PostMapping("{id}/deliver")
    @NotRepeat
    public String deliver(@PathVariable String id) {
        return taskOrderService.deliver(id);
    }

    @SaCheckRole("接单者")
    @PostMapping("{id}/confirm")
    @NotRepeat
    public String confirm(@PathVariable String id) {
        return taskOrderService.confirm(id);
    }

    @SaCheckRole("接单者")
    @PostMapping("{id}/accepted/cancel/deliver")
    @NotRepeat
    public String acceptedCancelForDeliver(@PathVariable String id) {
        return taskOrderService.acceptedCancelForDeliver(id);
    }

    @PostMapping("wallet-pay")
    public String walletPay(@RequestParam String id) {
        return taskOrderService.walletPay(id);
    }

    @PostMapping("create")
    @NotRepeat
    public String create(@RequestBody @Validated TaskOrderInput orderInput) {
        return taskOrderService.create(orderInput);
    }

    @PostMapping("{id}/prepay/wechat")
    @NotRepeat
    public WxPayUnifiedOrderV3Result.JsapiResult prepayWechat(@PathVariable String id) {
        return taskOrderService.prepay(id);
    }

    @PostMapping("notify/pay/wechat")
    @ApiIgnore
    public String paymentNotifyWechat(@RequestBody String body,
                                      @RequestHeader(value = "Wechatpay-Timestamp") String timestamp,
                                      @RequestHeader(value = "Wechatpay-Nonce") String nonce,
                                      @RequestHeader(value = "Wechatpay-Signature") String signature,
                                      @RequestHeader(value = "Wechatpay-Serial") String serial) {
        SignatureHeader signatureHeader = SignatureHeader.builder().signature(signature)
                .serial(serial)
                .nonce(nonce)
                .timeStamp(timestamp).build();
        return taskOrderService.paymentNotifyWechat(body, signatureHeader);
    }

    @PostMapping("{id}/unpaid/cancel/user")
    @NotRepeat
    public String unpaidCancelForUser(@PathVariable String id) {
        return taskOrderService.unpaidCancelForUser(id);
    }


    @PostMapping("notify/refund/wechat")
    @ApiIgnore
    public String refundNotifyWeChat(@RequestBody String body,
                                     @RequestHeader(value = "Wechatpay-Timestamp") String timestamp,
                                     @RequestHeader(value = "Wechatpay-Nonce") String nonce,
                                     @RequestHeader(value = "Wechatpay-Signature") String signature,
                                     @RequestHeader(value = "Wechatpay-Serial") String serial) {
        SignatureHeader signatureHeader = SignatureHeader.builder().signature(signature)
                .serial(serial)
                .nonce(nonce)
                .timeStamp(timestamp).build();
        return taskOrderService.refundNotifyWeChat(body, signatureHeader);
    }

    @PostMapping("calculate")
    public TaskOrderService.CalculateView calculate(@Validated @RequestBody TaskOrderInput taskOrderInput) {
        return taskOrderService.calculate(taskOrderInput);
    }


    @PostMapping("delete")
    public boolean delete(@RequestParam String id) {
        taskOrderRepository.deleteById(id);
        return true;
    }
}
